/**
 * 数字格式化工具类
 * @description 提供各种数字处理和格式化功能
 */
export class NumberUtils {
  /**
   * 格式化数字为货币格式
   * @param amount 金额
   * @param currency 货币符号
   * @param decimals 小数位数
   * @returns 格式化后的货币字符串
   */
  static formatCurrency(amount: number, currency: string = '¥', decimals: number = 2): string {
    if (typeof amount !== 'number' || isNaN(amount)) {
      return `${currency}0.00`;
    }

    const formattedAmount = amount.toFixed(decimals);
    const parts = formattedAmount.split('.');
    const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    const decimalPart = parts[1] ? `.${parts[1]}` : '';
    
    return `${currency}${integerPart}${decimalPart}`;
  }

  /**
   * 格式化数字为百分比
   * @param value 数值（0-1之间）
   * @param decimals 小数位数
   * @returns 百分比字符串
   */
  static formatPercentage(value: number, decimals: number = 1): string {
    if (typeof value !== 'number' || isNaN(value)) {
      return '0%';
    }

    return `${(value * 100).toFixed(decimals)}%`;
  }

  /**
   * 格式化数字为千分位格式
   * @param num 数字
   * @param decimals 小数位数
   * @returns 千分位格式的字符串
   */
  static formatThousands(num: number, decimals?: number): string {
    if (typeof num !== 'number' || isNaN(num)) {
      return '0';
    }

    const formattedNum = decimals !== undefined ? num.toFixed(decimals) : num.toString();
    const parts = formattedNum.split('.');
    const integerPart = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
    const decimalPart = parts[1] ? `.${parts[1]}` : '';
    
    return `${integerPart}${decimalPart}`;
  }

  /**
   * 格式化数字为简化格式（K, M, B等）
   * @param num 数字
   * @param decimals 小数位数
   * @returns 简化格式的字符串
   */
  static formatCompact(num: number, decimals: number = 1): string {
    if (typeof num !== 'number' || isNaN(num)) {
      return '0';
    }

    const absNum = Math.abs(num);
    const sign = num < 0 ? '-' : '';

    if (absNum >= 1e9) {
      return `${sign}${(absNum / 1e9).toFixed(decimals)}B`;
    } else if (absNum >= 1e6) {
      return `${sign}${(absNum / 1e6).toFixed(decimals)}M`;
    } else if (absNum >= 1e3) {
      return `${sign}${(absNum / 1e3).toFixed(decimals)}K`;
    } else {
      return `${sign}${absNum.toString()}`;
    }
  }

  /**
   * 格式化文件大小
   * @param bytes 字节数
   * @param decimals 小数位数
   * @returns 格式化后的文件大小
   */
  static formatFileSize(bytes: number, decimals: number = 2): string {
    if (typeof bytes !== 'number' || isNaN(bytes) || bytes === 0) {
      return '0 B';
    }

    const k = 1024;
    const dm = decimals < 0 ? 0 : decimals;
    const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];

    const i = Math.floor(Math.log(bytes) / Math.log(k));
    const size = parseFloat((bytes / Math.pow(k, i)).toFixed(dm));

    return `${size} ${sizes[i]}`;
  }

  /**
   * 格式化时长（秒转换为时分秒）
   * @param seconds 秒数
   * @param showSeconds 是否显示秒
   * @returns 格式化后的时长字符串
   */
  static formatDuration(seconds: number, showSeconds: boolean = true): string {
    if (typeof seconds !== 'number' || isNaN(seconds) || seconds < 0) {
      return '0秒';
    }

    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const remainingSeconds = Math.floor(seconds % 60);

    const parts: string[] = [];

    if (hours > 0) {
      parts.push(`${hours}小时`);
    }

    if (minutes > 0) {
      parts.push(`${minutes}分钟`);
    }

    if (showSeconds && (remainingSeconds > 0 || parts.length === 0)) {
      parts.push(`${remainingSeconds}秒`);
    }

    return parts.join('');
  }

  /**
   * 格式化分数为小数
   * @param numerator 分子
   * @param denominator 分母
   * @param decimals 小数位数
   * @returns 小数字符串
   */
  static formatFraction(numerator: number, denominator: number, decimals: number = 2): string {
    if (typeof numerator !== 'number' || typeof denominator !== 'number' || 
        isNaN(numerator) || isNaN(denominator) || denominator === 0) {
      return '0';
    }

    return (numerator / denominator).toFixed(decimals);
  }

  /**
   * 格式化评分显示
   * @param rating 评分
   * @param maxRating 最大评分
   * @param decimals 小数位数
   * @returns 评分字符串
   */
  static formatRating(rating: number, maxRating: number = 5, decimals: number = 1): string {
    if (typeof rating !== 'number' || isNaN(rating)) {
      return `0/${maxRating}`;
    }

    const clampedRating = Math.max(0, Math.min(rating, maxRating));
    return `${clampedRating.toFixed(decimals)}/${maxRating}`;
  }

  /**
   * 格式化进度百分比
   * @param current 当前值
   * @param total 总值
   * @param decimals 小数位数
   * @returns 进度百分比字符串
   */
  static formatProgress(current: number, total: number, decimals: number = 1): string {
    if (typeof current !== 'number' || typeof total !== 'number' || 
        isNaN(current) || isNaN(total) || total === 0) {
      return '0%';
    }

    const percentage = Math.max(0, Math.min(100, (current / total) * 100));
    return `${percentage.toFixed(decimals)}%`;
  }

  /**
   * 格式化数字范围
   * @param min 最小值
   * @param max 最大值
   * @param unit 单位
   * @returns 范围字符串
   */
  static formatRange(min: number, max: number, unit: string = ''): string {
    if (typeof min !== 'number' || typeof max !== 'number' || isNaN(min) || isNaN(max)) {
      return '';
    }

    if (min === max) {
      return `${min}${unit}`;
    }

    return `${min}${unit} - ${max}${unit}`;
  }

  /**
   * 格式化序数（1st, 2nd, 3rd等）
   * @param num 数字
   * @returns 序数字符串
   */
  static formatOrdinal(num: number): string {
    if (typeof num !== 'number' || isNaN(num)) {
      return '';
    }

    const absNum = Math.abs(num);
    const lastDigit = absNum % 10;
    const lastTwoDigits = absNum % 100;

    let suffix = 'th';
    if (lastTwoDigits < 11 || lastTwoDigits > 13) {
      switch (lastDigit) {
        case 1:
          suffix = 'st';
          break;
        case 2:
          suffix = 'nd';
          break;
        case 3:
          suffix = 'rd';
          break;
      }
    }

    return `${num}${suffix}`;
  }

  /**
   * 格式化中文数字序数（第一、第二等）
   * @param num 数字
   * @returns 中文序数字符串
   */
  static formatChineseOrdinal(num: number): string {
    if (typeof num !== 'number' || isNaN(num) || num < 1) {
      return '';
    }

    const chineseNumbers = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九', '十'];
    
    if (num <= 10) {
      return `第${chineseNumbers[num]}`;
    } else if (num < 20) {
      return `第十${chineseNumbers[num - 10]}`;
    } else {
      return `第${num}`;
    }
  }

  /**
   * 安全的数字运算（避免浮点数精度问题）
   * @param a 数字a
   * @param b 数字b
   * @param operation 运算类型
   * @returns 运算结果
   */
  static safeCalculate(a: number, b: number, operation: 'add' | 'subtract' | 'multiply' | 'divide'): number {
    if (typeof a !== 'number' || typeof b !== 'number' || isNaN(a) || isNaN(b)) {
      return 0;
    }

    // 获取小数位数
    const getDecimalPlaces = (num: number): number => {
      const str = num.toString();
      const decimalIndex = str.indexOf('.');
      return decimalIndex === -1 ? 0 : str.length - decimalIndex - 1;
    };

    const decimalPlacesA = getDecimalPlaces(a);
    const decimalPlacesB = getDecimalPlaces(b);
    const maxDecimalPlaces = Math.max(decimalPlacesA, decimalPlacesB);
    const multiplier = Math.pow(10, maxDecimalPlaces);

    const intA = Math.round(a * multiplier);
    const intB = Math.round(b * multiplier);

    let result: number;
    switch (operation) {
      case 'add':
        result = (intA + intB) / multiplier;
        break;
      case 'subtract':
        result = (intA - intB) / multiplier;
        break;
      case 'multiply':
        result = (intA * intB) / (multiplier * multiplier);
        break;
      case 'divide':
        result = intB === 0 ? 0 : intA / intB;
        break;
      default:
        result = 0;
    }

    return result;
  }

  /**
   * 检查数字是否在指定范围内
   * @param num 数字
   * @param min 最小值
   * @param max 最大值
   * @returns 是否在范围内
   */
  static isInRange(num: number, min: number, max: number): boolean {
    if (typeof num !== 'number' || typeof min !== 'number' || typeof max !== 'number' ||
        isNaN(num) || isNaN(min) || isNaN(max)) {
      return false;
    }

    return num >= min && num <= max;
  }

  /**
   * 将数字限制在指定范围内
   * @param num 数字
   * @param min 最小值
   * @param max 最大值
   * @returns 限制后的数字
   */
  static clamp(num: number, min: number, max: number): number {
    if (typeof num !== 'number' || isNaN(num)) {
      return min;
    }

    return Math.max(min, Math.min(max, num));
  }

  /**
   * 生成指定范围内的随机数
   * @param min 最小值
   * @param max 最大值
   * @param decimals 小数位数
   * @returns 随机数
   */
  static randomInRange(min: number, max: number, decimals: number = 0): number {
    if (typeof min !== 'number' || typeof max !== 'number' || isNaN(min) || isNaN(max)) {
      return 0;
    }

    const random = Math.random() * (max - min) + min;
    return decimals > 0 ? parseFloat(random.toFixed(decimals)) : Math.floor(random);
  }
}

/**
 * 导出便捷函数
 */

/**
 * 格式化货币
 */
export const formatCurrency = (amount: number, currency?: string, decimals?: number) => 
  NumberUtils.formatCurrency(amount, currency, decimals);

/**
 * 格式化百分比
 */
export const formatPercentage = (value: number, decimals?: number) => 
  NumberUtils.formatPercentage(value, decimals);

/**
 * 格式化千分位
 */
export const formatThousands = (num: number, decimals?: number) => 
  NumberUtils.formatThousands(num, decimals);

/**
 * 格式化简化数字
 */
export const formatCompact = (num: number, decimals?: number) => 
  NumberUtils.formatCompact(num, decimals);

/**
 * 格式化时长
 */
export const formatDuration = (seconds: number, showSeconds?: boolean) => 
  NumberUtils.formatDuration(seconds, showSeconds);

/**
 * 格式化评分
 */
export const formatRating = (rating: number, maxRating?: number, decimals?: number) => 
  NumberUtils.formatRating(rating, maxRating, decimals);

/**
 * 格式化进度
 */
export const formatProgress = (current: number, total: number, decimals?: number) => 
  NumberUtils.formatProgress(current, total, decimals);

/**
 * 格式化范围
 */
export const formatRange = (min: number, max: number, unit?: string) => 
  NumberUtils.formatRange(min, max, unit);

/**
 * 安全计算
 */
export const safeAdd = (a: number, b: number) => NumberUtils.safeCalculate(a, b, 'add');
export const safeSubtract = (a: number, b: number) => NumberUtils.safeCalculate(a, b, 'subtract');
export const safeMultiply = (a: number, b: number) => NumberUtils.safeCalculate(a, b, 'multiply');
export const safeDivide = (a: number, b: number) => NumberUtils.safeCalculate(a, b, 'divide');

/**
 * 数字范围检查
 */
export const isInRange = (num: number, min: number, max: number) => 
  NumberUtils.isInRange(num, min, max);

/**
 * 数字限制
 */
export const clamp = (num: number, min: number, max: number) => 
  NumberUtils.clamp(num, min, max);